package com.ingenico.insider.services.impl;

import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.logging.Logger;

import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.KeyStroke;

import com.ingenico.insider.util.Constants;

import net.infonode.docking.View;

public final class LocalisationSupplier {
	private static final Logger _logger = Logger.getLogger(LocalisationSupplier.class.getCanonicalName());

	/**
	 * The resource bundle that contains all the resources
	 */
	private static final ResourceBundle resourceBundle = ResourceBundle.getBundle(LocalisationSupplier.class.getSimpleName());

	/**
	 * Public constant keywords
	 */
	public static final String ACTION_KEY = "action";
	public static final String ACTION_BASE = Constants.INSIDER_BASE + Constants.SEPARATOR + ACTION_KEY;

	public static final String VIEW_KEY = "view";
	public static final String VIEW_BASE = Constants.INSIDER_BASE + Constants.SEPARATOR + VIEW_KEY;

	public static final String BUTTON_KEY = "button";
	public static final String BUTTON_BASE = Constants.INSIDER_BASE + Constants.SEPARATOR + BUTTON_KEY;

	public static final String STRING_KEY = "string";
	public static final String STRING_BASE = Constants.INSIDER_BASE + Constants.SEPARATOR + STRING_KEY;

	public static final String TITLE_KEY = "title";
	public static final String TOOLTIP_KEY = "tooltip";
	public static final String DESCRIPTION_KEY = "description";
	public static final String ICON_KEY = "icon";
	public static final String SMALL_ICON_KEY = ICON_KEY + Constants.SEPARATOR + "small";
	public static final String LARGE_ICON_KEY = ICON_KEY + Constants.SEPARATOR + "large";
	public static final String MNEMONIC_KEY = "mnemonic";
	public static final String ACCELERATOR_KEY = "accelerator";

	/**
	 * singleton instance
	 */
	private static LocalisationSupplier instance;

	/**
	 * private constructor of final class to prevent external instantiation
	 */
	private LocalisationSupplier() {
	}

	/**
	 * retrieve the singleton instance
	 *
	 * @return the LocalisationSupplier singleton
	 */
	public static LocalisationSupplier getInstance() {
		if (instance == null) {
			_logger.info(LocalisationSupplier.class.getName() + " instance does not exist... Creating instance.");
			instance = new LocalisationSupplier();
		}
		return instance;
	}

	public AbstractButton localize(final AbstractButton button, final String key) {
		final String baseKey = BUTTON_BASE + Constants.SEPARATOR + key;

		String resourceKey;
		String resourceValue;

		// MenuItem title
		resourceKey = baseKey + Constants.SEPARATOR + TITLE_KEY;
		try {
			resourceValue = resourceBundle.getString(resourceKey);
			_logger.fine("Setting MenuItem Title: " + resourceKey + " = " + resourceValue);
			button.setText(resourceValue);
		} catch (MissingResourceException mre) {
			button.setText(key);
			_logger.severe("Resource Key Missing (" + resourceKey + "). MenuItem Title set to key value");
		}

		// MenuItem tooltip
		resourceKey = baseKey + Constants.SEPARATOR + TOOLTIP_KEY;
		try {
			resourceValue = resourceBundle.getString(resourceKey);
			if ((resourceValue != null) && ( ! resourceValue.isEmpty())) {
				_logger.fine("Setting MenuItem Tooltip: " + resourceKey + " = " + resourceValue);
				button.setToolTipText(resourceValue);
			} else {
				_logger.info("Resource Key empty (" + resourceKey + "). MenuItem Tooltip not set");
			}
		} catch (MissingResourceException mre) {
			_logger.warning("Resource Key Missing (" + resourceKey + "). MenuItem Tooltip not set");
		}

		// MenuItem icon
		resourceKey = baseKey + Constants.SEPARATOR + ICON_KEY;
		try {
			resourceValue = resourceBundle.getString(resourceKey);
			if ((resourceValue != null) && ( ! resourceValue.isEmpty())) {
				_logger.fine("Setting MenuItem Icon: " + resourceKey + " = " + resourceValue);
				button.setIcon(new ImageIcon(getClass().getClassLoader().getResource(resourceValue)));
			} else {
				_logger.info("Resource Key Empty (" + resourceKey + "). MenuItem Icon not set");
			}
		} catch (MissingResourceException mre) {
			_logger.warning("Resource Key Missing (" + resourceKey + "). MenuItem Icon not set");
		}

		// MenuItem mnemonic
		resourceKey = baseKey + Constants.SEPARATOR + MNEMONIC_KEY;
		try {
			resourceValue = resourceBundle.getString(resourceKey);
			if ((resourceValue != null) && ( ! resourceValue.isEmpty())) {
				if (resourceValue.length() != 1) {
					_logger.severe("Invalid MenuItem Mnemonic: " + resourceKey + " = \"" + resourceValue + "\". MenuItem Mnemonic not set");
				} else {
					char mnemonic = resourceValue.charAt(0);
					_logger.fine("Setting MenuItem Mnemonic: " + resourceKey + " = '" + mnemonic + "'");
					button.setMnemonic(mnemonic);
				}
			} else {
				_logger.info("Resource Key Empty (" + resourceKey + "). MenuItem Mnemonic not set");
			}
		} catch (MissingResourceException mre) {
			_logger.warning("Resource Key Missing (" + resourceKey + "). MenuItem Mnemonic not set");
		}

		// Once the button or the menu item is set up, return it
		return button;
	}

	/**
	 * Initializes an action from the resource file.
	 * 
	 * @param view the view whose settings will be modified according to the resource file contents
	 * @param key the view name in the properties file
	 * @return the modified view
	 */
	public View localize(final View view, final String key) {
		final String baseKey = VIEW_BASE + Constants.SEPARATOR + key;
		String resourceKey;
		String resourceValue;

		// View title
		resourceKey = baseKey + Constants.SEPARATOR + TITLE_KEY;
		try {
			resourceValue = resourceBundle.getString(resourceKey);
			_logger.fine("Setting View Title: " + resourceKey + " = " + resourceValue);
			view.getViewProperties().setTitle(resourceValue);
		} catch (MissingResourceException mre) {
			view.getViewProperties().setTitle(key);
			_logger.severe("Resource Key Missing (" + resourceKey + "). View Title set to key value");
		}

		// View tooltip
		resourceKey = baseKey + Constants.SEPARATOR + TOOLTIP_KEY;
		try {
			resourceValue = resourceBundle.getString(resourceKey);
			if ((resourceValue != null) && ( ! resourceValue.isEmpty())) {
				_logger.fine("Setting View Tooltip: " + resourceKey + " = " + resourceValue);
				view.setToolTipText(resourceValue);
			} else {
				_logger.info("Resource Key empty (" + resourceKey + "). View Tooltip not set");
			}
		} catch (MissingResourceException mre) {
			_logger.warning("Resource Key Missing (" + resourceKey + "). View Tooltip not set");
		}

		// View icon
		resourceKey = baseKey + Constants.SEPARATOR + ICON_KEY;
		try {
			resourceValue = resourceBundle.getString(resourceKey);
			if ((resourceValue != null) && ( ! resourceValue.isEmpty())) {
				_logger.fine("Setting View Icon: " + resourceKey + " = " + resourceValue);
				view.getViewProperties().setIcon(new ImageIcon(getClass().getClassLoader().getResource(resourceValue)));
			} else {
				_logger.info("Resource Key Empty (" + resourceKey + "). View Icon not set");
			}
		} catch (MissingResourceException mre) {
			_logger.warning("Resource Key Missing (" + resourceKey + "). View Icon not set");
		}

		// Once the view is set up, return it
		return view;
	}

	/**
	 * Initializes an action from the resource file.
	 *
	 * @param action the action whose settings will be modified according to the resource file contents 
	 * @param key the action name in the properties file
	 * @return the modified action
	 */
	public Action localize(final Action action, final String key) {
		final String baseKey = ACTION_BASE + Constants.SEPARATOR + key;
		String resourceKey;
		String resourceValue;

		// Action title
		resourceKey = baseKey + Constants.SEPARATOR + TITLE_KEY;
		try {
			resourceValue = resourceBundle.getString(resourceKey);
			if ((resourceValue != null) && ( ! resourceValue.isEmpty())) {
				_logger.fine("Setting Action.NAME: " + resourceKey + " = " + resourceValue);
				action.putValue (Action.NAME, resourceValue);
			} else {
				_logger.info("Resource Key empty (" + resourceKey + "). Action.NAME not set");
			}
		} catch (MissingResourceException mre) {
			action.putValue (Action.NAME, key);
			_logger.warning("Resource Key Missing (" + resourceKey + "). Action.NAME set to key value");
		}

		// Action tooltip
		resourceKey = baseKey + Constants.SEPARATOR + TOOLTIP_KEY;
		try {
			resourceValue = resourceBundle.getString(resourceKey);
			if ((resourceValue != null) && ( ! resourceValue.isEmpty())) {
				_logger.fine("Setting Action.SHORT_DESCRIPTION: " + resourceKey + " = " + resourceValue);
				action.putValue (Action.SHORT_DESCRIPTION, resourceValue);
			} else {
				_logger.info("Resource Key empty (" + resourceKey + "). Action.SHORT_DESCRIPTION not set");
			}
		} catch (MissingResourceException mre) {
			_logger.warning("Resource Key Missing (" + resourceKey + "). Action.SHORT_DESCRIPTION not set");
		}

		// Action description
		resourceKey =  baseKey + Constants.SEPARATOR + DESCRIPTION_KEY;
		try {
			resourceValue = resourceBundle.getString(resourceKey);
			if ((resourceValue != null) && ( ! resourceValue.isEmpty())) {
				_logger.fine("Setting Action.LONG_DESCRIPTION: " + resourceKey + " = " + resourceValue);
				action.putValue (Action.LONG_DESCRIPTION, resourceValue);
			} else {
				_logger.info("Resource Key empty (" + resourceKey + "). Action.LONG_DESCRIPTION not set");
			}
		} catch (MissingResourceException mre) {
			_logger.warning("Resource Key Missing (" + resourceKey + "). Action.LONG_DESCRIPTION not set");
		}

		// Action small icon
		resourceKey = baseKey + Constants.SEPARATOR + SMALL_ICON_KEY;
		try {
			resourceValue = resourceBundle.getString(resourceKey);
			if ((resourceValue != null) && ( ! resourceValue.isEmpty())) {
				_logger.fine("Setting Action.SMALL_ICON: " + resourceKey + " = " + resourceValue);
				action.putValue(Action.SMALL_ICON, new ImageIcon(getClass().getClassLoader().getResource(resourceValue)));
			} else {
				_logger.info("Resource Key empty (" + resourceKey + "). Action.SMALL_ICON not set");
			}
		} catch (MissingResourceException mre) {
			_logger.warning("Resource Key Missing (" + resourceKey + "). Action.SMALL_ICON not set");
		}

		// Action large icon
		resourceKey = baseKey + Constants.SEPARATOR + LARGE_ICON_KEY;
		try {
			resourceValue = resourceBundle.getString(resourceKey);
			if ((resourceValue != null) && ( ! resourceValue.isEmpty())) {
				_logger.fine("Setting Action.LARGE_ICON_KEY: " + resourceKey + " = " + resourceValue);
				action.putValue(Action.LARGE_ICON_KEY, new ImageIcon(getClass().getClassLoader().getResource(resourceValue)));
			} else {
				_logger.info("Resource Key empty (" + resourceKey + "). Action.LARGE_ICON_KEY not set");
			}
		} catch (MissingResourceException mre) {
			_logger.warning("Resource Key Missing (" + resourceKey + "). Action.LARGE_ICON_KEY not set");
		}

		// Action mnemonic
		resourceKey = baseKey + Constants.SEPARATOR + MNEMONIC_KEY;
		try {
			resourceValue = resourceBundle.getString(resourceKey);
			if ((resourceValue != null) && ( ! resourceValue.isEmpty())) {
				if (resourceValue.length() != 1) {
					_logger.severe("Invalid Action Mnemonic: " + resourceKey + " = \"" + resourceValue + "\". Action Mnemonic not set");
				} else {
					char mnemonic = resourceValue.charAt(0);
					_logger.fine("Setting Action.MNEMONIC_KEY: " + resourceKey + " = '" + mnemonic + "'");
					
					// We convert the mnemonic to an int because KeyEvent.VK_?
					// are mapped to ascii codes (for instance VK_A = 0x41)
					action.putValue(Action.MNEMONIC_KEY, (int)mnemonic);
				}
			} else {
				_logger.info("Resource Key Empty (" + resourceKey + "). Action.MNEMONIC_KEY not set");
			}
		} catch (MissingResourceException mre) {
			_logger.warning("Resource Key Missing (" + resourceKey + "). Action.MNEMONIC_KEY not set");
		}

		// Action mnemonic
		resourceKey = baseKey + Constants.SEPARATOR + ACCELERATOR_KEY;
		try {
			resourceValue = resourceBundle.getString(resourceKey);
			if ((resourceValue != null) && ( ! resourceValue.isEmpty())) {
				KeyStroke accelerator = KeyStroke.getKeyStroke(resourceValue);
				if (accelerator == null) {
					_logger.severe("Invalid Action Accelerator: " + resourceKey + " = \"" + resourceValue + "\". MenuItem Mnemonic not set");
				} else {
					_logger.fine("Setting Action.ACCELERATOR_KEY: " + resourceKey + " = '" + resourceValue + "'");
					action.putValue(Action.ACCELERATOR_KEY, accelerator);						
				}
			} else {
				_logger.info("Resource Key Empty (" + resourceKey + "). Action.ACCELERATOR_KEY not set");
			}
		} catch (MissingResourceException mre) {
			_logger.warning("Resource Key Missing (" + resourceKey + "). Action.ACCELERATOR_KEY not set");
		}

		// Once the action is set up, return it
		return action;
	}
	
	public String localize (final String key) {
		final String baseKey = STRING_BASE + Constants.SEPARATOR + key;
		String resourceKey;
		String resourceValue;

		resourceKey = baseKey + Constants.SEPARATOR + TITLE_KEY;
		try {
			resourceValue = resourceBundle.getString(resourceKey);
			if ((resourceValue != null) && ( ! resourceValue.isEmpty())) {
				_logger.fine("Setting String: " + resourceKey + " = " + resourceValue);
				return resourceValue;
			} else {
				_logger.warning("Resource Key empty (" + resourceKey + "). resource string empty");
				return resourceValue;
			}
		} catch (MissingResourceException mre) {
			_logger.severe("Resource Key Missing (" + resourceKey + "). resource string set to key value");
			return key;
		}
	}
}
